package impl

import (
	"context"
	"errors"
	"fmt"
	"github.com/starmotioncf/common/log"
	"github.com/starmotioncf/common/third_account"
	"github.com/starmotioncf/soutchatinternal/constant/redis_key"
	"github.com/starmotioncf/soutchatinternal/model"
	"github.com/starmotioncf/soutchatinternal/repository"
	"strconv"
	"time"

	"github.com/redis/go-redis/v9"
	"github.com/spf13/cast"
)

type accountRepository struct {
	*repository.Repository
}

func NewAccountRepository(r *repository.Repository) repository.AccountRepository {
	return &accountRepository{
		Repository: r,
	}
}

// GetAuthByIdentifier 获取对应的uid
func (r *accountRepository) GetAuthByIdentifier(ctx context.Context, identityType third_account.IdentityType, identifier string) (m *model.UserAuth, err error) {
	err = r.DB(ctx).Model(&model.UserAuth{}).
		Where("identity_type = ? and identifier = ?", identityType, identifier).First(&m).Error
	return
}

// UnbindAuth 解绑
func (r *accountRepository) UnbindAuth(ctx context.Context, uid uint64, identType third_account.IdentityType) error {
	return r.DB(ctx).Where("uid = ? and identity_type = ?", uid, identType).Delete(&model.UserAuth{}).Error
}

// GetBindAuths 获取当前绑定数量
func (r *accountRepository) GetBindAuths(ctx context.Context, uid uint64) (total int64, err error) {
	err = r.DB(ctx).Model(&model.UserAuth{}).Where("uid = ?", uid).Count(&total).Error
	return
}

// UpdatePassword 修改密码
func (r *accountRepository) UpdatePassword(ctx context.Context, userAuth *model.UserAuth, password string) error {
	return r.DB(ctx).Model(&model.UserAuth{}).Where("id = ?", userAuth.Id).
		Updates(map[string]any{
			"credential": password,
			"updated_at": time.Now().Unix(),
		}).Error
}

// LoginAuth 登录时的更新操作
func (r *accountRepository) LoginAuth(ctx context.Context, userAuth *model.UserAuth, accessToken string, expireTs int64) error {
	err := r.DB(ctx).Model(&model.UserAuth{}).Where("id = ?", userAuth.Id).Updates(map[string]any{
		"access_token": accessToken,
		"updated_at":   time.Now().Unix(),
	}).Error
	if err == nil {
		//token写入redis
		key := redis_key.UserAccessToken.ToString()
		field := strconv.FormatUint(userAuth.Uid, 10)
		res := r.RDB().HSet(ctx, key, cast.ToString(userAuth.Uid), accessToken)
		if res.Err() != nil {
			log.Log().Error("token写入redis失败：" + res.Err().Error())
			return res.Err()
		}
		r.RDB().HExpireAt(ctx, key, time.Unix(expireTs, 0), field)
	}
	return err
}

// GetCurrentAccessToken 获取一个用户当前的token，放在redis，过期时间为token的过期时间
func (r *accountRepository) GetCurrentAccessToken(ctx context.Context, uid uint64) string {
	rk := redis_key.UserAccessToken.ToString()
	token, err := r.RDB().HGet(ctx, rk, strconv.FormatUint(uid, 10)).Result()
	if err != nil {
		if !errors.Is(err, redis.Nil) && !errors.Is(err, context.Canceled) {
			log.Log().Error(fmt.Sprintf("GetCurrentAccessToken[%d] error:%s", uid, err))
		}
		// get from database
		return ""
	}
	return token
}

// RemoveAccessToken 移除用户token，会造成重新登录
func (r *accountRepository) RemoveAccessToken(ctx context.Context, uid uint64) error {
	rk := redis_key.UserAccessToken.ToString()
	return r.RDB().HDel(ctx, rk, strconv.FormatUint(uid, 10)).Err()
}

// CreateAuth 创建
func (r *accountRepository) CreateAuth(ctx context.Context, m *model.UserAuth) (err error) {
	err = r.DB(ctx).Create(&m).Error
	return
}

// // ExistsByMobilePhone 检查电话号码是否存在
//
//	func (r *accountRepository) ExistsByMobilePhone(ctx context.Context, mobilePhone string) (bool, error) {
//		newMp := utils2.TrimMobilePhone(mobilePhone)
//		if newMp == "" {
//			return false, resp.ErrMobilePhone
//		}
//		total := int64(0)
//		err := r.DB(ctx).Model(&model.VcUserAuth{}).Where("identity_type = ? and identifier = ? and unbind = 0", constant.IdentityTypeMobilePhone, mobilePhone).
//			Count(&total).Error
//		if total > 0 {
//			return true, nil
//		}
//		if err == nil && total == 0 {
//			if newMp != mobilePhone {
//				err = r.DB(ctx).Model(&model.VcUserAuth{}).
//					Where("identity_type = ? and  identifier = ? and unbind = 0", constant.IdentityTypeMobilePhone, newMp).Count(&total).Error
//			} else {
//				err = r.DB(ctx).Model(&model.VcUserAuth{}).
//					Where("identity_type = ? and  identifier = ? and unbind = 0", constant.IdentityTypeMobilePhone, "0"+newMp).Count(&total).Error
//			}
//		}
//		return total > 0, err
//
//		//
//		//mobilePhone = utils.RemoveNonDigits(mobilePhone)
//		//total := int64(0)
//		//err := r.DB(ctx).Model(&model.VcUserAuth{}).Where("identity_type = ? and identifier = ? and unbind = 0", constant.IdentityTypeMobilePhone, mobilePhone).
//		//	Count(&total).Error
//		//if total > 0 {
//		//	return true, nil
//		//}
//		//newMp := utils.RemoveLeftZero(mobilePhone)
//		//if newMp != mobilePhone {
//		//	err = r.DB(ctx).Model(&model.VcUserAuth{}).Where("identity_type = ? and identifier = ? and unbind = 0", constant.IdentityTypeMobilePhone, newMp).
//		//		Count(&total).Error
//		//}
//		//return total > 0, err
//	}
//
// // GetAuthByUidAndType 获取uid对应的登录类型
//
//	func (r *accountRepository) GetAuthByUidAndType(ctx context.Context, uid uint64, identType constant.IdentityType) (m *model.VcUserAuth, err error) {
//		userAuth := model.VcUserAuth{}
//		err = r.DB(ctx).Model(&model.VcUserAuth{}).Where("uid = ? and identity_type = ? and unbind = 0", uid, identType).
//			First(&userAuth).Error
//		return &userAuth, err
//	}
//
// // GetLastLoginByMac 获取最后一次登录
//
//	func (r *accountRepository) GetLastLoginByMac(ctx context.Context, mac string) (m *model.VcUserAuth, err error) {
//		sql := "select vc_user_auth.* from vc_user_login_log left join vc_user_auth on vc_user_auth.id = vc_user_login_log.login_auth"
//		sql += "  where vc_user_login_log.mac = ? and vc_user_login_log.login_auth>0 and vc_user_auth.unbind = 0 order by  ts desc limit 1"
//		err = r.DB(ctx).Raw(sql, mac).Scan(&m).Error
//		return
//	}
//
// // GetUserAuthList 获取用户登录列表
//
//	func (r *accountRepository) GetUserAuthList(ctx context.Context, uid uint64) (m []*model.VcUserAuth, err error) {
//		err = r.DB(ctx).Where("uid = ? and unbind = 0", uid).Find(&m).Error
//		return
//	}
//
//	func (r *accountRepository) GetCountByMac(ctx context.Context, mac string) int64 {
//		//  select count(DISTINCT uid) from vc_user_login_log where mac="6D745BB4-DB6F-411B-849E-05C75BD7EF04"
//		cc := int64(0)
//		_ = r.DB(ctx).Model(&model.VcUserLoginLog{}).Where("mac = ?", mac).Select("count(DISTINCT uid) as cc").Pluck("cc", &cc).Error
//		return cc
//	}
//
//	func (r *accountRepository) GetCountByMacAndTimes(ctx context.Context, mac string, afterTime time.Duration) int64 {
//		//  select count(DISTINCT uid) from vc_user_login_log where mac="6D745BB4-DB6F-411B-849E-05C75BD7EF04"
//		cc := int64(0)
//		//type=2是注册
//		_ = r.DB(ctx).Model(&model.VcUserLoginLog{}).Where("mac = ? and ts > ? and type = 2", mac, time.Now().Add(-afterTime).Unix()).
//			Select("count(DISTINCT uid) as cc").Pluck("cc", &cc).Error
//		return cc
//	}
//
//	func (r *accountRepository) GetCountByIp(ctx context.Context, loginIp string, afterTime time.Duration) int64 {
//		// sql := "select count(*) from (select count(*) from vc_user_login_log where loginip = ? and logintime > ?  group by uid) as a"
//		//err := orm.NewOrm().Raw(sql, ip, time.Now().Add(-time.Hour*24*7).Format(pp.TIME_FORMAT)).QueryRow(&num)
//		cc := int64(0)
//		_ = r.DB(ctx).Model(&model.VcUserLoginLog{}).Where("loginip = ? and ts > ? and type = 2", loginIp, time.Now().Add(-afterTime).Unix()).
//			Select("count(DISTINCT uid) as cc").Pluck("cc", &cc).Error
//		return cc
//	}

func (r *accountRepository) CreateRegisterInfo(ctx context.Context, m *model.UserRegisterInfo) error {
	return r.DB(ctx).Create(&m).Error
}

func (r *accountRepository) CreateLoginRecord(ctx context.Context, m *model.UserLoginRecord) error {
	return r.DB(ctx).Create(&m).Error
}
